package com.sc.byahi.user.client.components.rating;

import java.util.Iterator;

import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.sc.byahi.user.client.AppController;
import com.sc.byahi.user.client.ICleaner;
import com.sc.byahi.user.shared.constants.Config;

public class NewRating extends FocusPanel implements HasValue<Long>, HasMouseOutHandlers, HasMouseOverHandlers, ICleaner {

	private final FlowPanel panel;
	private Long profileId;

	private Long currentRating = new Long(0);
	private Long hoverValue = Config.NO_RATING;

	private static Image imageSel = new Image("/images/star-selected.png");
	private static Image imageUnsel = new Image("/images/star-unselected.png");
	private static Image imageHover = new Image("/images/star-hover.png");
	boolean noEvent = false;
	boolean doubleClick = false;

	@Override
	public void clean() {
		profileId = null;
		currentRating = Config.NO_RATING;
		hoverValue = Config.NO_RATING;
		noEvent = false;
	}
	/**
	 * Use this if it is used for generic searches or generic filtering.
	 */
	public NewRating() {
		super(new FlowPanel());
		panel = (FlowPanel) getWidget();
		panel.setWidth("80px");
		for (Long rating = Config.MIN_RATING; rating <= Config.MAX_RATING; ++rating) {
			panel.add(new Star(rating));
		}
		setStarHover(Config.NO_RATING);
	}

	/**
	 * Use this if it is used in profileViewDiv
	 * 
	 * @param profileId
	 */
	public void setProfileId(Long profileId) {
		this.profileId = profileId;
	}
	
	/**
	 * If noEvent is false, no event will be sent to AppController
	 * use this is static places, like profilesearch view.
	 * @param noEvent
	 */
	public void setMode(boolean noEvent) {
		this.noEvent= noEvent;
	}
	
	/**
	 * If doubleClick is false, doubleclick will behave just like single click, i.e. setting value to the star value.
	 * If it is true, then it will remove ratings, used only in search criteria.
	 * @param noEvent
	 */
	public void setDoubleClick(boolean doubleClick) {
		this.doubleClick= doubleClick;
	}

	public Long getValue() {
		return currentRating;
	}

	/**
	 * Used for setting init threshold value, so that AppController doesn't go in infinite loop
	 * @param value
	 */
	public void setInitValue(Long value) {
		currentRating = value;
		setStarHover(currentRating);
	}

	public void setValue(Long value) {
		setValue(value, true);
	}

	public void setValue(Long value, boolean fireEvents) {
		final Long oldValue = currentRating;
		currentRating = value;
		setStarHover(Config.NO_RATING);
		if (profileId == null) {
			if(!noEvent)
				AppController.get().ratingThresholdChanged(currentRating);
		} else {
			AppController.get().ratingChanged(profileId, currentRating);
		}
		if (fireEvents) {
			ValueChangeEvent.fireIfNotEqual(this, oldValue, value);
		}
	}

	public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Long> handler) {
		return addHandler(handler, ValueChangeEvent.getType());
	}

	@Override
	public void onBrowserEvent(Event event) {
		super.onBrowserEvent(event);
	}

	private void setStarHover(Long index) {
		Iterator<Widget> starIterator = panel.iterator();

		while (starIterator.hasNext()) {
			Object nextElement = starIterator.next();
			Star currStar = (Star) nextElement;
			if (currStar.getIndex() <= index) {
				currStar.setImage(imageHover.getUrl());
			} else if (currStar.getIndex() <= currentRating) {
				currStar.setImage(imageSel.getUrl());
			} else {
				currStar.setImage(imageUnsel.getUrl());
			}
		}
	}

	class Star extends Image {

		private final Long index;

		public Star(Long index) {
			sinkEvents(Event.MOUSEEVENTS | Event.ONCLICK);
			this.index = index;

			switch (index.intValue()) {
			case 1:
				setTitle("Later");
				break;
			case 2:
				setTitle("Maybe");
				break;
			case 3:
				setTitle("Average");
				break;
			case 4:
				setTitle("Good");
				break;
			case 5:
				setTitle("Shortlisted");
				break;
			}
		}

		public void setImage(String img) {
			super.setUrl(img);
		}

		public Long getIndex() {
			return index;
		}

		@Override
		public void onBrowserEvent(Event event) {
			switch (event.getTypeInt()) {
			case Event.ONMOUSEOVER:
				hoverValue = getIndex();
				setStarHover(hoverValue);
				MouseOverEvent.fireNativeEvent(event, NewRating.this);
				break;
			case Event.ONMOUSEOUT:
				hoverValue = Config.NO_RATING;
				setStarHover(hoverValue);
				MouseOutEvent.fireNativeEvent(event, NewRating.this);
				break;
			case Event.ONCLICK:
				setValue(getIndex());
				break;
			case Event.ONDBLCLICK:
				if(doubleClick)
					setValue(Config.NO_RATING);
				else
					setValue(getIndex());
				break;
			default:
				super.onBrowserEvent(event);
			}
		}
	}


}
